#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include "msg_queue_peer.h"

#include "MQTTClient.h"
#include "shmem.h"
#include "cJSON.h"

#define ADDRESS "tcp://mqtt.yyzlab.com.cn:1883"
#define CLIENTID "ExampleClientSub"
#define TOPIC "2429295153/Device2AIOTSIM"
#define LAYET "2429295153/APP2AIOTSIM"
#define QOS 1
#define TIMEOUT 10000L

// 消息队列结构体
struct msgbuf
{
    long mtype;
    char mdata[256];
};

volatile MQTTClient_deliveryToken deliveredtoken;
MQTTClient_deliveryToken token;

void delivered(void *context, MQTTClient_deliveryToken dt)
{
    printf("Message with token value %d delivery confirmed\n", dt);
    deliveredtoken = dt;
}

/**
 * @brief
 *
 * @param context
 * @param topicName 收到来自哪个主题的消息
 * @param topicLen 主题的长度
 * @param message 消息体:payload(消息体，字符串)  payloadlen：消息的长度
 * @return int
 */
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    int i;
    char *payloadptr;

    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("   message: ");
#if 0
    payloadptr = message->payload;
    for(i=0; i<message->payloadlen; i++)
    {
        putchar(*payloadptr++);
    }
#endif
    printf("recv msg = %s\n", (char *)message->payload);

    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
}

void connlost(void *context, char *cause)
{
    printf("\nConnection lost\n");
    printf("     cause: %s\n", cause);
}

int main(int argc, char *argv[])
{
    // 客户端句柄（描述符）
    MQTTClient client;
    // 连接参数
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    int rc;
    int ch;
    char *sendMsg;
    // 创建客户端，并且指定客户端连接的mqtt服务器地址和客户端ID
    MQTTClient_create(&client, ADDRESS, CLIENTID,
                      MQTTCLIENT_PERSISTENCE_NONE, NULL);

    // 初始化连接参数
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;

    // 设置回调接口，只需要关注msgarrvd：消息到达后，会自动调用这个接口
    MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);

    // 连接到broker
    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

    printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
           "Press Q<Enter> to quit\n\n",
           TOPIC, CLIENTID, QOS);

    // 订阅某个主题，指定订阅主题的名字，可以指定qos服务质量
    MQTTClient_subscribe(client, TOPIC, QOS);

    struct msgbuf recv_buf;

    while (1)
    {

        printf("---------------------%d\n", __LINE__);

        // 从消息队列接收消息
        if (msg_queue_recv("metaServer", &recv_buf, sizeof(recv_buf), 0, 0) > 0)
        {
            printf("recv from msga type = %ld\n", recv_buf.mtype);
            printf("recv from msga data = %s\n", recv_buf.mdata);
        }
        else
        {
            perror("recv error:");
            return -1;
        }
        printf("---------------------%d\n", __LINE__);

        cJSON *root = cJSON_Parse(recv_buf.mdata);

        cJSON *metaServer = cJSON_GetObjectItem(root, "metaServer");

        cJSON *key = cJSON_GetObjectItem(metaServer, "key");

        int keyValue = key->valueint;

        cJSON *sendRoot = cJSON_CreateObject();

        cJSON *value = cJSON_GetObjectItem(metaServer, "value");
        int valueValue = value->valueint;
        printf("value = %d\n", valueValue);
        MQTTClient_message pubmsg = MQTTClient_message_initializer;

        switch (keyValue)
        {
            // 人体红外
        case 3001:
            cJSON_AddStringToObject(sendRoot, "id", "1234567");
            cJSON_AddNumberToObject(sendRoot, "infrared", valueValue ? 31 : 30);
            sendMsg = cJSON_PrintUnformatted(sendRoot);
            pubmsg.payload = sendMsg;            // 消息体
            pubmsg.payloadlen = strlen(sendMsg); // 消息长度
            pubmsg.qos = QOS;                    // 服务质量
            pubmsg.retained = 0;                 // 不保留消息
            MQTTClient_publishMessage(client, LAYET, &pubmsg, &token);
            printf("sendMsg = %s\n", sendMsg);
            break;

        // 烟雾
        case 3002:
            cJSON_AddNumberToObject(sendRoot, "smog", valueValue ? 31 : 30);
            sendMsg = cJSON_PrintUnformatted(sendRoot);
            pubmsg.payload = sendMsg;            // 消息体
            pubmsg.payloadlen = strlen(sendMsg); // 消息长度
            pubmsg.qos = QOS;                    // 服务质量
            pubmsg.retained = 0;                 // 不保留消息
            MQTTClient_publishMessage(client, LAYET, &pubmsg, &token);
            printf("sendMsg = %s\n", sendMsg);
            break;

        // 遮阳
        case 3003:
            if (valueValue == 0)
                cJSON_AddStringToObject(sendRoot, "sunshade", "stop");
            else if (valueValue == 0)
                cJSON_AddStringToObject(sendRoot, "sunshade", "forward");
            else if (valueValue == 2)
                cJSON_AddStringToObject(sendRoot, "sunshade", "reverse");

            sendMsg = cJSON_PrintUnformatted(sendRoot);
            pubmsg.payload = sendMsg;            // 消息体
            pubmsg.payloadlen = strlen(sendMsg); // 消息长度
            pubmsg.qos = QOS;                    // 服务质量
            pubmsg.retained = 0;                 // 不保留消息
            MQTTClient_publishMessage(client, LAYET, &pubmsg, &token);
            printf("sendMsg = %s\n", sendMsg);

            break;
        // 风扇
        case 3004:
            cJSON_AddStringToObject(sendRoot, "fan", valueValue ? "true" : "false");
            sendMsg = cJSON_PrintUnformatted(sendRoot);
            pubmsg.payload = sendMsg;            // 消息体
            pubmsg.payloadlen = strlen(sendMsg); // 消息长度
            pubmsg.qos = QOS;                    // 服务质量
            pubmsg.retained = 0;                 // 不保留消息
            MQTTClient_publishMessage(client, LAYET, &pubmsg, &token);
            printf("sendMsg = %s\n", sendMsg);

            break;
        // 灯
        case 3005:
            cJSON_AddStringToObject(sendRoot, "lamp", valueValue ? "true" : "false");
            sendMsg = cJSON_PrintUnformatted(sendRoot);
            pubmsg.payload = sendMsg;            // 消息体
            pubmsg.payloadlen = strlen(sendMsg); // 消息长度
            pubmsg.qos = QOS;                    // 服务质量
            pubmsg.retained = 0;                 // 不保留消息
            MQTTClient_publishMessage(client, LAYET, &pubmsg, &token);
            printf("sendMsg = %s\n", sendMsg);

            break;
        // 门锁
        case 3006:
            cJSON_AddStringToObject(sendRoot, "doorlock", valueValue ? "true" : "false");
            sendMsg = cJSON_PrintUnformatted(sendRoot);
            pubmsg.payload = sendMsg;            // 消息体
            pubmsg.payloadlen = strlen(sendMsg); // 消息长度
            pubmsg.qos = QOS;                    // 服务质量
            pubmsg.retained = 0;                 // 不保留消息
            MQTTClient_publishMessage(client, LAYET, &pubmsg, &token);
            printf("sendMsg = %s\n", sendMsg);
            break;
        // 道闸
        case 3007:
            cJSON_AddStringToObject(sendRoot, "barrierGate", valueValue ? "true" : "false");
            sendMsg = cJSON_PrintUnformatted(sendRoot);
            pubmsg.payload = sendMsg;            // 消息体
            pubmsg.payloadlen = strlen(sendMsg); // 消息长度
            pubmsg.qos = QOS;                    // 服务质量
            pubmsg.retained = 0;                 // 不保留消息
            MQTTClient_publishMessage(client, LAYET, &pubmsg, &token);
            printf("sendMsg = %s\n", sendMsg);
            break;

        default:
            break;
        }
    }

    MQTTClient_unsubscribe(client, TOPIC);
    MQTTClient_disconnect(client, 10000);
    MQTTClient_destroy(&client);
    return rc;
}
